package aoshiScript.entity;

import java.awt.Color;
import java.awt.Point;
import java.awt.Robot;
import java.util.*;

import commons.entity.Constant;
import commons.entity.NativeCp;
import destinychild.entity.DcPointInfo;
import destinychild.entity.TaskInfo;
import fgoScript.exception.AppNeedRestartException;
import fgoScript.exception.AppNeedStopException;
import fgoScript.exception.AppNeedUpdateException;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.melloware.jintellitype.JIntellitype;

import fgoScript.entity.panel.FgoFrame;
import fgoScript.constant.GameConstant;
import fgoScript.entity.PointColor;
import fgoScript.entity.BaseZButton;
import commons.util.GameUtil;
import commons.util.PropertiesUtil;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.swing.*;

public class WuNa implements IWuNa{
	private static final Logger LOGGER = LogManager.getLogger(WuNa.class);
	private boolean GO = false;
	private boolean allStop = false;
	private Long lastClickTime;
	private Long firstClickTime;
	boolean scucess = true;
	boolean ifThrowException = false;
	private String eName;
	private final DcPointInfo DC_POINTINFO = DcPointInfo.getSpringBean();
	private ThreadPoolTaskExecutor circleTPExcutor;
	private int minValues = 10;
	public void setCircleTPExcutor(ThreadPoolTaskExecutor circleTPExcutor) {
		this.circleTPExcutor = circleTPExcutor;
	}

	public String geteName() {
		return eName;
	}

	public void seteName(String eName) {
		this.eName = eName;
	}

	@Override
	public boolean isScucess() {
		return scucess;
	}

	@Override
	public void setScucess(boolean scucess) {
		this.scucess = scucess;
	}

	private String name;
	private int count ;
	private int clickCount ;
	public WuNa(String name) {
		super();
		this.name = name;
	}
	
	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	public Long getFirstClickTime() {
		return firstClickTime;
	}

	public void setFirstClickTime(Long firstClickTime) {
		this.firstClickTime = firstClickTime;
	}

	@Override
	public void setLastClickTime(Long lastClickTime) {
		this.lastClickTime = lastClickTime;
	}

	@Override
	public Long getLastClickTime() {
		return lastClickTime;
	}

	@Override
	public boolean isGO() {
		return GO;
	}
	@Override
	public void setGO(boolean go) {
		GO = go;
	}

	@Override
	public boolean isAllStop() {
		return allStop;
	}

	@Override
	public void setAllStop(boolean forceStop) {
		this.allStop = forceStop;
	}

	public int getClickCount() {
		return clickCount;
	}
	public void setClickCount(int clickCount) {
		this.clickCount = clickCount;
	}
	@Override
	public void alwaysClick() {
		setAllStop(false);
        if (isGO()) {
			setGO(false);
		} else{
			setGO(true);
		}
        if (isGO()){
            Robot rb = GameUtil.getRb();
            int factor = getFactor();
            String startegy = PropertiesUtil.getValueFromFileNameAndKey("clickStrategy" , "changeButton_" + NativeCp.getUserName(), "");
            if (startegy.equals("判断")) {
				try {
					String relativePath = "CK/";
					String fileName = PropertiesUtil.getValueFromCKFile("CKName");
					alwaysClickForStrategy(fileName, null, false, false, false, false,0,relativePath,null);
				} catch (AppNeedRestartException e) {
					LOGGER.error(e.getMessage(),e);
				} catch (AppNeedStopException e) {
					e.printStackTrace();
				}
			}else if (startegy.equals("按住")) {
				GameUtil.getMymouse().mousePress();

            }else {
				while (isGO()) {
					GameUtil.getMymouse().mousePressAndRelease(factor);
				}
			}
        }

	}
	private int getFactor(){
		String multiFactor = PropertiesUtil.getValueFromFileNameAndKey("multiFactor" , "changeButton_" + NativeCp.getUserName(),"");
		int factor = Integer.parseInt(multiFactor.trim());
		return factor;
	}
	@Override
	public void alwaysClickForStrategy(String fileName,Integer factor,boolean alwaysGo
            , boolean clickWait,boolean checkOutTime
            , boolean checkMissionPC, int outTime
            , String relativePath, TaskInfo taskInfo) throws AppNeedRestartException, AppNeedStopException {
		// 初始化参数
		setScucess(true);
		setGO(true);
		setLastClickTime(System.currentTimeMillis());
		Robot rb = GameUtil.getRb();
		String condiTion = PropertiesUtil.getValueFromAutoClickFile("condiTion", fileName, relativePath);
		String action = PropertiesUtil.getValueFromAutoClickFile("action", fileName, relativePath);
		condiTion = StringUtils.isBlank(condiTion) ? "" : condiTion.substring(0, condiTion.length()-1);
		action = StringUtils.isBlank(action) ? "" : action.substring(0, action.length()-1);
		String[] pcStr = condiTion.split(";");
		String[] acStr = action.split(";");
		int size = pcStr.length;
		int len = acStr.length;
		if (StringUtils.isBlank(condiTion)) {
			JOptionPane.showMessageDialog(null, "请点击设置按键！", "信息", JOptionPane.INFORMATION_MESSAGE);
			setGO(false);
			setScucess(false);
		}else if(StringUtils.isBlank(action) || size!=len){
			JOptionPane.showMessageDialog(null, "按键不完整，请补全或重新设置！", "信息", JOptionPane.WARNING_MESSAGE);
			setGO(false);
			setScucess(false);
		}else {
			int minSize = size < len ? size:len;
			if (size!=len) {
//				LOGGER.info("配置不成对，忽略最后一次点击");
			}
			List<PointColor> pcList = new ArrayList<>();
			List<Integer> onceList = new ArrayList<>();
			List<Integer> delayList = new ArrayList<>();
			List<List<Point>> dragPointList = new ArrayList<>();
			List<Point> onedragPointList = new ArrayList<>();
			String pointStr;
			String colorStr;
			String onceStr;
			String delayStr;
			String dragStr;
			String[] dragPointxy;
			int conditionSize;
			String[] tempArray;
			String[] dragPointArray;


			for (int i = 0; i < minSize; i++) {
				tempArray = pcStr[i].split("_");
				conditionSize = tempArray.length;
				pointStr = tempArray[0];
				colorStr = tempArray[1];
				if (conditionSize > 2) {
					onceStr = tempArray[2];
				}else {
					onceStr = "-1";
				}
				if (conditionSize > 3) {
					delayStr = tempArray[3];
				}else {
					delayStr = "0";
				}
				if (conditionSize > 4) {
					dragStr = tempArray[4];
				}else {
					dragStr = "-1";
				}

				onceList.add(Integer.valueOf(onceStr));
				delayList.add(Integer.valueOf(delayStr));

				dragPointArray = dragStr.split(":");
				onedragPointList = new ArrayList<>();
				for (int j = 0; j < dragPointArray.length; j++) {
					if(dragStr == "-1"){
					}else{
						dragPointxy=dragPointArray[j].split(",");
						onedragPointList.add(new Point(Integer.parseInt(dragPointxy[0]),Integer.parseInt(dragPointxy[1])));
					}
				}
				dragPointList.add(onedragPointList);
				pcList.add(new PointColor(new Point(Integer.parseInt(pointStr.split(",")[0]),
						Integer.parseInt(pointStr.split(",")[1])),
						new Color(Integer.parseInt(colorStr.split(",")[0]),
								Integer.parseInt(colorStr.split(",")[1]),
								Integer.parseInt(colorStr.split(",")[2])), true));

			}
			List<Point> pList = new ArrayList<>();
			for (int i = 0; i < minSize; i++) {
				pList.add(new Point(Integer.parseInt(acStr[i].split(",")[0]),
						Integer.parseInt(acStr[i].split(",")[1])));
			}
			PointColor pointColor = null;
			Point p;
			Point pA;
			Point pB;
			Color c0;
			Color c1;
			Color lastC = null;
			int sameCounts = 0;
			boolean flag = true;
			boolean isEqual;
			String className = this.getClass().getName();
			Random r=new Random();
			int ri;
			int[] riArray;
			// 启动另一个线程：检测超时
			circleTPExcutor.execute(new Runnable() {
				@Override
				public void run() {
					try {
						stopOutTimeClick(alwaysGo, checkOutTime, checkMissionPC, outTime, taskInfo);
					} catch (AppNeedRestartException e) {
						LOGGER.error(e.getMessage(),e);
						seteName(e.getName());
						setIfThrowException(true);
					} catch (AppNeedStopException e) {
						LOGGER.error(e.getMessage(),e);
					}
				}
			});
			//循环点色点击
			LOGGER.info("《《《执行检测点击，对应脚本文件名： "+fileName + "》》》");
			long time = System.currentTimeMillis();
			while ((isGO() || alwaysGo) && !isAllStop() && System.currentTimeMillis()-time < 10 * 60 * 1000){
				minSize = pcList.size();
				riArray = getRandomArray(minSize);
				if(minSize==0){
					LOGGER.info("NO POINTS");
					break;
				}
				if(GameUtil.isFORCE_OUTTIME()){
					GameUtil.setFORCE_OUTTIME(false);
					break;
				}
				for (int i = 0; i < minSize && !isAllStop(); i++) {
					if (ifThrowException) {
						setIfThrowException(false);
						AppNeedRestartException ar = new AppNeedRestartException();
						ar.setName(geteName());
						throw ar;
					}
					ri = riArray[i];
					pointColor = pcList.get(ri);
					p = pointColor.getPoint();
					c0 = pointColor.getColor();
					isEqual = pointColor.isEqual();
					c1 = GameUtil.getScreenPixel(p);
					flag = GameUtil.likeEqualColor(c0, c1, minValues);
					if (!isEqual) {
						flag = !flag;
					}
					if (flag) {
						if(sameCounts > 50){
							throw new AppNeedRestartException();
						}
                        if (c0.equals(lastC)){
							GameUtil.delay(200);
                            sameCounts++;
                        }else{
                            sameCounts=0;
                            lastC = c0;
                        }
						setLastClickTime(System.currentTimeMillis());
						if(dragPointList.get(ri) !=null && dragPointList.get(ri).size()!=0){
							pA = new Point((int) dragPointList.get(ri).get(0).getX(), (int) dragPointList.get(ri).get(0).getY());
							pB = new Point((int) dragPointList.get(ri).get(1).getX(), (int) dragPointList.get(ri).get(1).getY());
							GameUtil.getMymouse().moveBySteps(pA,pB);

						}else{
//							LOGGER.info("移动( " + pList.get(ri).getX()+"_"+pList.get(ri).getY()+" )");
							GameUtil.getMymouse().mouseMoveByPoint(new Point((int) pList.get(ri).getX(), (int) pList.get(ri).getY()),true,true);

//							LOGGER.info("左键单击");
							GameUtil.getMymouse().mousePressAndRelease(20);

//							GameUtil.delay(20);
						}


						if (clickWait) {
							GameUtil.delay(1000);
						}
						GameUtil.delay(1000*delayList.get(ri));
						int z = onceList.get(ri);
						if((--z) == 0){
							pcList.remove(ri);
							pList.remove(ri);
							onceList.remove(ri);
							delayList.remove(ri);
							dragPointList.remove(ri);
							GameUtil.delay(1000);
							break;
						}
//						LOGGER.info("当前次数： "+z);
						onceList.set(ri,z);

					}
					rb.delay(factor == null ? 5 * getFactor() : factor);
					GameUtil.ifPauseScript();
				}
			};
		}
		while(circleTPExcutor.getActiveCount()!=0){
			GameUtil.delay(1000);
			LOGGER.info("wait for Stop clock!");
		}
		LOGGER.info("Finish auto click scanning!");

	}
	private int[] getRandomArray(int length){
		int[] arr = new int[length];//10个数的数组
		for (int i = 0; i < arr.length; i++) {
			//生产一个1-20的随机数
			int index = (int)(Math.random() * length );
			arr[i] = index;//把随机数赋值给下标为数组下标为i的值
			//（遍历数组中储存进去的值，i中有几个值则循环几次）
			for (int j = 0; j < i; j++)
			{
				//把储存在数组中的值j 和 随机出的值i 做比较
				if (arr[j] == arr[i])
				{
					i--; //数组的值下标-1，i的循环次数回到上次
					break;
				}
			}
		}
		return arr;
	}
	private static void putRandomNumberIntoArrays(int[] arrays) {
		int datalength =arrays.length;
		for (int i = 0; i < arrays.length; i++) {
			arrays[i]= i+1;
		}
		do{
			int  rand =new Random().nextInt(datalength--);
			int tmp=arrays[rand];
			arrays[rand] = arrays[datalength];
			arrays[datalength] = tmp;
		}while(datalength>0);
	}
	@Override
	public void configClick(BaseZButton bt) {
		String text = bt.getText();
		if ("点击设置".equals(text)) {
			bt.setText("选择条件");
		} else if ("选择条件".equals(text)){
			selectConditionPoint();
			bt.setText("选择结果");
		} else if ("选择结果".equals(text)){
			selectActionPoint();
			bt.setText("选择条件");
		}
	}
	@Override
	public void falshClick(BaseZButton bt) {
		Map<String, BaseZButton> btsMaps = FgoFrame.instance().getBtsMaps();
		BaseZButton setbt = btsMaps.get("点击设置");
		setbt.setEnabled(true);
		setbt.setText("点击设置");
		JIntellitype.getInstance().unregisterHotKey(setbt.getMarkCode());
		this.setClickCount(0);
		PropertiesUtil.deleteAutoClickFile();
	}
	private void selectConditionPoint() {
		Point p = GameUtil.getMousePosition();
		Color c = GameUtil.getScreenPixel(p);
		String condiTion = (int) p.getX()+"," + (int) p.getY()
		+ "_" + c.getRed() + "," +c.getGreen()	+ "," +c.getBlue()		
		+ ";";
		String temp = PropertiesUtil.getValueFromAutoClickFile("condiTion", "");
		condiTion = (StringUtils.isBlank(temp)?"":temp) + condiTion;
		Map<String, String> map = new HashMap<>();
		map.put("condiTion", condiTion);
		PropertiesUtil.setValueForAutoClick(map);
	}
	private void selectActionPoint() {
		Point p = GameUtil.getMousePosition();
		String action = (int) p.getX()+"," + (int) p.getY()
		+ ";";
		String temp = PropertiesUtil.getValueFromAutoClickFile("action", "");
		action = (StringUtils.isBlank(temp)?"":temp) + action;
		Map<String, String> map = new HashMap<>();
		map.put("action", action);
		PropertiesUtil.setValueForAutoClick(map);
	}
	private  void mousePressAndRelease(int key) {
		GameUtil.getMymouse().mousePressAndRelease(GameConstant.DELAY/4);
	}

	public boolean isIfThrowException() {
		return ifThrowException;
	}

	@Override
	public void setIfThrowException(boolean ifThrowException) {
		this.ifThrowException = ifThrowException;
	}

	private void stopOutTimeClick(boolean alwaysGo, boolean checkOutTime, boolean checkMissionPC, int outTime, TaskInfo taskInfo) throws AppNeedRestartException, AppNeedStopException {
		setFirstClickTime(System.currentTimeMillis());
		int check = 0;
		int outCounts = 0;
		long latestMinus;
		long firstMinus;
		while (isGO() && checkOutTime){
			latestMinus = this.getLastClickTime() == null ? 0 : System.currentTimeMillis() - this.getLastClickTime();
			firstMinus = this.getFirstClickTime() == null ? 0 : System.currentTimeMillis() - this.getFirstClickTime();
			if ( latestMinus > outTime*1000) {
				if (GameUtil.likeEqualColor(GameUtil.getScreenPixel(DC_POINTINFO.getLoading().getPoint()),DC_POINTINFO.getLoading().getColor(),10)){
					LOGGER.info("进度圈等待中！");
					GameUtil.delay(3000);
				} else {
					if(outCounts++ % 10 == 0 ){
						LOGGER.info("《《计时记录器超时》》" + outTime+"秒");
					}
					if(GameUtil.isWAIT_FLAG()){
						this.setLastClickTime(System.currentTimeMillis());
					}else{
						this.setGO(false);
					}
				}
			}else{
				outCounts=0;
			}
			if ( firstMinus > 60*60*1000) {
				LOGGER.info("《《运行超1小时！》》");
                throw new AppNeedRestartException();
			}
			// 意外检查
			if (check != 0 && (check % 8 == 0)) {
				try {
					GameUtil.waitInteruptSolution(check, Constant.DCMonitor);
				} catch (AppNeedUpdateException e) {
					LOGGER.error(e.getMessage(),e);
				}
			}
			//进入时，首页检测
			if(taskInfo!=null && checkMissionPC && GameUtil.likeEqualColor(GameUtil.getScreenPixel(taskInfo.getMissionPc().getPoint()),
												taskInfo.getMissionPc().getColor())){
				LOGGER.info("<<已经到达了任务首页>>");
				this.setGO(false);
				GameUtil.delay(3000);
			}
			GameUtil.delay(1000);
			check++;
		}
	}

	public void setMinValues(int minValues) {
		this.minValues = minValues;
	}

	public static void main(String[] args) {
		Logger LOGGER = LogManager.getLogger(WuNa.class);
		LOGGER.info("333333");
		LOGGER.error("44444");

	}
}
